package cn.ryh.gatewaycode.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 若一个请求能匹配到多个路由，则按最先匹配的路由进行转发(顺序为哪个路由配置的在最前面则最先匹配)
 * @author Rao
 * @Description Gateway代码配置方式
 * @create 2021-12-07 17:55
 */
@Configuration
public class GatewayConfig {
    /**
     * 可以通过链式的.route配置多个规则，也可以是通过声明多个方法的方式。（推荐链式）
     * @param routeLocator
     * @return
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocator) {
        RouteLocatorBuilder.Builder routes = routeLocator.routes();
        /*
         * route：
         * 参数一类似与数据库主键，非重复得标识位
         * 参数二对应断言得请求路径，可以有多个
         * 参数三对应断言结果，如果为true则跳转映射uri中
         * 转发规则为
         *  例:
         *      localhost:9527/guonei 转发 为 http://news.baidu.com/guonei
         *      localhost:9527/guoji  转发 为 http://news.baidu.com/guoji
         *   结论为 转发地址为 uri的服务器地址替换本地的服务器地址
         */
        routes.route("path", r -> r.path("/guonei")
                .uri("http://news.baidu.com/"))
                .route("path2", r -> r.path("/guoji")
                        .uri("http://news.baidu.com/guojiwwwwwwwwwwwwwwww/"))
                .route("path3", r -> r.path("/")
                        .uri("https://www.baidu.com"))
                .route("path4", r -> r.path("/baidu")
                        .uri("https://www.baidu.com"))
                /*
                 开启动态路由需要在yml配置文件中添加
                    spring:
                      cloud:
                        gateway:
                          discovery:
                            locator:
                              enabled: true #开启从注册中心动态创建路由的功能，利用微服务名进行路由
                  默认情况下Gateway会根据注册中心的服务列表，以注册中心上微服务名为路径创建动态路由进行转发，从而实现动态路由的功能
                  需要注意的是uri的协议为lb，表示启用Gateway的负载均衡功能。
                   lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡ur
                 */
                .route("path5", r -> r.path("/payment/**")
                /*
                    #- After=2021-03-08T10:59:34.102+08:00[Asia/Shanghai] 在该时间之后才能进行访问
                    #- Before=2021-03-08T12:59:34.102+08:00[Asia/Shanghai] 在该时间之前才能进行访问
                    #- Between=2021-03-08T12:59:34.102+08:00[Asia/Shanghai],2021-03-18T12:59:34.102+08:00[Asia/Shanghai]
                    #   在该时间区间内才能访问
                    #- Cookie=username,zhangshuai #俩个参数：一个是属性名称和一个正则表达式，这个属性值和正式表达式匹配才能访问
                    #   Cookie是username=zhangshuai才能访问
                    #- Header=X-Request-Id, \d+ #俩个参数：一个是属性名称和一个正则表达式，这个属性值和正式表达式匹配才能访问
                    #     例：X-Request-Id:123
                    #- Host=**.atguigu.com
                    #- Method=GET # 对应的访问方式 GET POST等
                    #- Query=username, \d+ #要有参数名称并且是正整数才能路由
                    #总结:Predicate就是为了实现一组匹配规则，让请求过来找到对应的Route进行处理
                 */
//                        .and().after(ZonedDateTime.now())
//                        .and().before(ZonedDateTime.now())
//                        .and().between(ZonedDateTime.now(),ZonedDateTime.now())
//                        .and().cookie("username","zhangshuai")
//                        .and().header()
//                        .and().host()
//                        .and().method()
//                        .and().path()
//                        .and().query()
                        .filters(f -> f.addRequestHeader("X-AnotherHeader", "baz"))
                        .uri("lb://CLOUD-PAYMENT-SERVICE"))
                .build();
        return routes.build();
    }

    /**
     * 该配置也是生效的
     * @param routeLocator
     * @return
     */
    @Bean
    public RouteLocator customRouteLocator2(RouteLocatorBuilder routeLocator) {
        RouteLocatorBuilder.Builder routes = routeLocator.routes();
        /**
         * route：
         * 参数一类似与数据库主键，非重复得标识位
         * 参数二对应断言得请求路径，可以有多个
         * 参数三对应断言结果，如果为true则跳转映射uri中
         * 转发规则为
         *  例:
         *      localhost:9527/guonei 转发 为 http://news.baidu.com/guonei
         *      localhost:9527/guoji  转发 为 http://news.baidu.com/guoji
         *   结论为 转发地址为 uri的服务器地址替换本地的服务器地址
         */
        routes.route("2path", r -> r.path("/mil")
                        .uri("http://news.baidu.com/"))
                .route("2path", r -> r.path("/**")
                        .uri("http://news.baidu.com/guojiwwwwwwwwwwwwwwww/"))
                .build();
        return routes.build();
    }
}
